﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Aceso.Server.DAL
{
    public class BaseRepository<TContext, TEntity> : IRepository<TEntity>
        where TContext : DbContext, new()
        where TEntity : class
    {
        protected TContext _context;
        protected readonly IDbSet<TEntity> _set;

        protected BaseRepository(TContext t)
        {
            _context = t;
        }

        protected TContext Context
        {
            get
            {
                return _context;
            }
        }

        protected IDbSet<TEntity> DbSet
        {
            get
            {
                return _set == null ? _context.Set<TEntity>() : _set;
            }
        }
        public int Count
        {
            get { return DbSet.Count(); }
        }

        //************编辑**************
        public virtual TEntity Add(TEntity TObject)
        {
            return DbSet.Add(TObject);
        }
        public virtual TEntity Update(TEntity TObject)
        {
            try
            {
                if (TObject != null)
                {
                    var entry = Context.Entry(TObject);
                    DbSet.Attach(TObject);
                    entry.State = EntityState.Modified;
                }
                return TObject;
            }
            catch (OptimisticConcurrencyException ex)
            {
                throw ex;
            }
        }
        public virtual int Delete(TEntity TObject)
        {
            if (Context.Entry(TObject).State == EntityState.Detached)
            {
                DbSet.Attach(TObject);
            }
            //Context.Entry(TObject).State = EntityState.Deleted;
            DbSet.Remove(TObject);
            return -1;
        }

        public virtual int Delete(Expression<Func<TEntity, bool>> predicate)
        {
            var objects = LoadEntities(predicate);
            foreach (var obj in objects)
            {
                //Context.Entry(obj).State = EntityState.Deleted;
                DbSet.Remove(obj);
            }
            return -1;
        }

        //************查询**************

        public IQueryable<TEntity> GetAll()
        {
            return DbSet.AsQueryable();
        }

        public virtual IQueryable<TEntity> LoadEntities(Expression<Func<TEntity, bool>> predicate)
        {
            return DbSet.Where<TEntity>(predicate).AsQueryable<TEntity>();
        }

        public virtual IQueryable<TEntity> LoadPageEntities(Expression<Func<TEntity, bool>> predicate, out int totalCount, int pageIndex = 1,
                                               int pageSize = 20)
        {
            var skipCount = (pageIndex-1) * pageSize;
            var resetSet = predicate != null
                                ? DbSet.Where<TEntity>(predicate).AsQueryable()
                                : DbSet.AsQueryable();
            resetSet = resetSet.Skip(skipCount).Take(pageSize);
            //resetSet = skipCount == 0 ? resetSet.Take(pageSize) : resetSet.Skip(skipCount).Take(pageSize);
            totalCount = resetSet.Count();
            return resetSet.AsQueryable();
        }
        ////分页查询
        //public virtual IQueryable<T> LoadPageEntities<S>(
        //    Expression<Func<T, bool>> whereLambada,
        //    Expression<Func<T, S>> orderBy,
        //    int pageSize,
        //    int pageIndex,
        //    out int totalCount,
        //    bool isASC)
        //{
        //    totalCount = db.Set<T>().Where(whereLambada).Count();
        //    IQueryable<T> entities = null;
        //    if (isASC)
        //    {
        //        entities = db.Set<T>().Where(whereLambada)
        //            .OrderBy(orderBy)
        //            .Skip(pageSize * (pageIndex - 1))
        //            .Take(pageSize);
        //    }
        //    else
        //    {
        //        entities = db.Set<T>().Where(whereLambada)
        //            .OrderByDescending(orderBy)
        //            .Skip(pageSize * (pageIndex - 1))
        //            .Take(pageSize);
        //    }
        //    return entities;
        //}
        public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate)
        {
            return GetAll().FirstOrDefault<TEntity>(predicate);
        }
        public bool Contains(Expression<Func<TEntity, bool>> predicate)
        {
            return DbSet.Any(predicate);
        }
        public virtual TEntity Find(params object[] keys)
        {
            return DbSet.Find(keys);
        }
        public virtual int CountWithCondition(Expression<Func<TEntity, bool>> predicate)
        {
            return DbSet.Where(predicate).Count();
        }
        public IQueryable<TEntity> GetWithRawSql(string query, params object[] parameters)
        {
            return Context.Database.SqlQuery<TEntity>(query, parameters).AsQueryable();
        }
    }
}
